package com.sxz.mall.ware.service.impl;

import com.sxz.mall.common.dto.SkuHasStockDto;
import com.sxz.mall.common.utils.R;
import com.sxz.mall.ware.entity.PurchaseDetailEntity;
import com.sxz.mall.ware.exception.NoStockException;
import com.sxz.mall.ware.feign.ProductFeignService;
import com.sxz.mall.ware.vo.LockStockResult;
import com.sxz.mall.ware.vo.OrderItemVo;
import com.sxz.mall.ware.vo.WareSkuLockVO;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sxz.mall.common.utils.PageUtils;
import com.sxz.mall.common.utils.Query;

import com.sxz.mall.ware.dao.WareSkuDao;
import com.sxz.mall.ware.entity.WareSkuEntity;
import com.sxz.mall.ware.service.WareSkuService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;


@Service("wareSkuService")
public class WareSkuServiceImpl extends ServiceImpl<WareSkuDao, WareSkuEntity> implements WareSkuService {

    @Autowired
    private WareSkuDao skuDao;

    @Autowired
    private ProductFeignService feignService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        QueryWrapper<WareSkuEntity> wrapper = new QueryWrapper<>();
        String skuId = (String) params.get("skuId");
        if (!StringUtils.isEmpty(skuId)) {
            wrapper.and(w -> {
                w.eq("sku_id", skuId);
            });
        }
        String wareId = (String) params.get("wareId");
        if (!StringUtils.isEmpty(wareId)) {
            wrapper.and(w -> {
                w.eq("ware_id", wareId);
            });
        }
        IPage<WareSkuEntity> page = this.page(
                new Query<WareSkuEntity>().getPage(params),
                wrapper
        );

        return new PageUtils(page);
    }

    @Override
    public void addStock(PurchaseDetailEntity detailEntity) {
        // 需要判断是否有库存记录，更新  、  插入
        Long wareId = detailEntity.getWareId();
        Long skuId = detailEntity.getSkuId();
        Integer skuNum = detailEntity.getSkuNum();
//        List<WareSkuEntity> list = this.list(new QueryWrapper<WareSkuEntity>().eq("ware_id", wareId)
//                .eq("sku_id", skuId));
        List<WareSkuEntity> list = skuDao.selectList(new QueryWrapper<WareSkuEntity>().eq("sku_id", skuId)
                .eq("ware_id", wareId));
        if (list == null || list.size() == 0) { // 插入
            WareSkuEntity wareSkuEntity = new WareSkuEntity();
            wareSkuEntity.setWareId(wareId);
            wareSkuEntity.setSkuId(skuId);
            wareSkuEntity.setStock(skuNum);
            wareSkuEntity.setStockLocked(0);
            // feign跨系统获取sku_id对应的名称
            try {
                R info = feignService.info(skuId);
//                Object object = info.get("skuInfo");
                Map<String, Object> data = (Map<String, Object>) info.get("skuInfo");
                if (info.getCode() == 0) {
                    wareSkuEntity.setSkuName((String) data.get("skuName"));
                }
            } catch (Exception e) {

                e.printStackTrace();
            }

            skuDao.insert(wareSkuEntity);
        } else { // 更新
            WareSkuEntity entity = list.get(0);
            WareSkuEntity wareSkuEntity = new WareSkuEntity();
            wareSkuEntity.setId(entity.getId());
            wareSkuEntity.setStock(entity.getStock() + skuNum);
            this.updateById(wareSkuEntity);
        }

    }

    // 获取每个skuId的库存信息
    @Override
    public List<SkuHasStockDto> getSkusHasStock(List<Long> skuIds) {
        List<SkuHasStockDto> list = skuIds.stream().map(item -> {
            SkuHasStockDto skuHasStockDto = new SkuHasStockDto();
            Long count = baseMapper.getSkuStock(item);

            skuHasStockDto.setSkuId(item);
            skuHasStockDto.setHasStock(count > 0);
            return skuHasStockDto;
        }).collect(Collectors.toList());
        return list;
    }


    @Transactional
    @Override
    public Boolean orderLockStock(WareSkuLockVO lockVO) {

        // 获取记录集合
        List<OrderItemVo> lockVOItems = lockVO.getItems();
        // 遍历查看每个商品的库存信息（一般有多个仓库可以出库）
        List<SkuWareStock> stockList = lockVOItems.stream().map((item) -> {
            SkuWareStock skuWareStock = new SkuWareStock();
            skuWareStock.setSkuId(item.getSkuId());
            skuWareStock.setNum(item.getCount());

            // 查询可以出库的仓库wareids
            List<WareSkuEntity> wareList = this.list(new QueryWrapper<WareSkuEntity>().
                    eq("sku_id", item.getSkuId()));

            skuWareStock.setWareList(wareList);
            return skuWareStock;
        }).collect(Collectors.toList());

        // 尝试锁定库存
        for (SkuWareStock stock : stockList) {
            Long skuId = stock.getSkuId();
            List<WareSkuEntity> wareList = stock.getWareList();
            // 所有仓库都没货，抛异常，给调用者捕获
            if (wareList == null || wareList.size() == 0) {
                throw new NoStockException(skuId);
            }

            Integer num = stock.getNum();
            // 锁定仓库，可能需要多个仓库一起出库才够数量
            for (WareSkuEntity wareSkuEntity : wareList) {
                int canLockNum = wareSkuEntity.getStock() - wareSkuEntity.getStockLocked();
                if (num <= canLockNum) { // 第一个仓库足够锁定,锁定并退出循环
                    wareSkuEntity.setStockLocked(wareSkuEntity.getStockLocked() + num);
                    boolean b = this.updateById(wareSkuEntity);
                    System.out.println("锁库存实际情况：" + b);
                    num = 0;
                    break;
                } else {
                    wareSkuEntity.setStockLocked(wareSkuEntity.getStockLocked() + canLockNum);
                    boolean b = this.updateById(wareSkuEntity);
                    System.out.println("锁库存实际情况：" + b);
                    num = num - canLockNum;
                }
            }

            System.out.println("还需要锁定的num：" + num);

            if (num > 0) { // 没有锁定成功，所有库存不够
                throw new NoStockException(skuId);
            }

        }
        return true;
    }

    @Data
    class SkuWareStock {
        private Long skuId;
        private Integer num; // 需要锁定的数量
        private List<WareSkuEntity> wareList; // 可以出库的仓库列表

    }

}